.TH std::tuple::tuple 3 "2024.06.10" "http://cppreference.com" "C++ Standard Libary"
.SH NAME
std::tuple::tuple \- std::tuple::tuple

.SH Synopsis
   Defined in header <tuple>
   constexpr tuple();                                     \fB(1)\fP  \fI(since C++11)\fP
                                                               (conditionally explicit)
                                                               \fI(since C++11)\fP
   tuple( const Types&... args );                         \fB(2)\fP  (constexpr since C++14)
                                                               (conditionally explicit)
   template< class... UTypes >                                 \fI(since C++11)\fP
   tuple( UTypes&&... args );                             \fB(3)\fP  (constexpr since C++14)
                                                               (conditionally explicit)
   template< class... UTypes >                            \fB(4)\fP  (since C++23)
   constexpr tuple( tuple<UTypes...>& other );                 (conditionally explicit)
   template< class... UTypes >                                 \fI(since C++11)\fP
   tuple( const tuple<UTypes...>& other );                \fB(5)\fP  (constexpr since C++14)
                                                               (conditionally explicit)
   template< class... UTypes >                                 \fI(since C++11)\fP
   tuple( tuple<UTypes...>&& other );                     \fB(6)\fP  (constexpr since C++14)
                                                               (conditionally explicit)
   template< class... UTypes >                            \fB(7)\fP  (since C++23)
   constexpr tuple( const tuple<UTypes...>&& other );          (conditionally explicit)
   template< class U1, class U2 >                         \fB(8)\fP  (since C++23)
   constexpr tuple( std::pair<U1, U2>& p );                    (conditionally explicit)
   template< class U1, class U2 >                              \fI(since C++11)\fP
   tuple( const std::pair<U1, U2>& p );                   \fB(9)\fP  (constexpr since C++14)
                                                               (conditionally explicit)
   template< class U1, class U2 >                              \fI(since C++11)\fP
   tuple( std::pair<U1, U2>&& p );                        \fB(10)\fP (constexpr since C++14)
                                                               (conditionally explicit)
   template< class U1, class U2 >                         \fB(11)\fP (since C++23)
   constexpr tuple( const std::pair<U1, U2>&& p );             (conditionally explicit)
   template< tuple-like UTuple >                          \fB(12)\fP (since C++23)
   constexpr tuple( UTuple&& u );                              (conditionally explicit)
   tuple( const tuple& other ) = default;                 \fB(13)\fP \fI(since C++11)\fP
   tuple( tuple&& other ) = default;                      \fB(14)\fP \fI(since C++11)\fP
   Allocator-extended constructors
   template< class Alloc >                                     \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a );         \fB(15)\fP (constexpr since C++20)
                                                               (conditionally explicit)
   template< class Alloc >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(16)\fP (constexpr since C++20)
                                                               (conditionally explicit)
          const Types&... args );
   template< class Alloc, class... UTypes >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(17)\fP (constexpr since C++20)
                                                               (conditionally explicit)
          UTypes&&... args );
   template< class Alloc, class... UTypes >
                                                               (since C++23)
   constexpr tuple( std::allocator_arg_t, const Alloc& a, \fB(18)\fP (conditionally explicit)

                    tuple<UTypes...>& other );
   template< class Alloc, class... UTypes >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(19)\fP (constexpr since C++20)
                                                               (conditionally explicit)
          const tuple<UTypes...>& other );
   template< class Alloc, class... UTypes >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(20)\fP (constexpr since C++20)
                                                               (conditionally explicit)
          tuple<UTypes...>&& other );
   template< class Alloc, class... UTypes >
                                                               (since C++23)
   constexpr tuple( std::allocator_arg_t, const Alloc& a, \fB(21)\fP (conditionally explicit)

                    const tuple<UTypes...>&& other );
   template< class Alloc, class U1, class U2 >
                                                               (since C++23)
   constexpr tuple( std::allocator_arg_t, const Alloc& a, \fB(22)\fP (conditionally explicit)

                    std::pair<U1, U2>& p );
   template< class Alloc, class U1, class U2 >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(23)\fP (constexpr since C++20)
                                                               (conditionally explicit)
          const std::pair<U1, U2>& p );
   template< class Alloc, class U1, class U2 >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(24)\fP (constexpr since C++20)
                                                               (conditionally explicit)
          std::pair<U1, U2>&& p );
   template< class Alloc, class U1, class U2 >
                                                               (since C++23)
   constexpr tuple( std::allocator_arg_t, const Alloc& a, \fB(25)\fP (conditionally explicit)

                    const std::pair<U1, U2>&& p );
   template< class Alloc, tuple-like UTuple >                  (since C++23)
   constexpr tuple( std::allocator_arg_t, const Alloc& a, \fB(26)\fP (conditionally explicit)
   UTuple&& u );
   template< class Alloc >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(27)\fP (constexpr since C++20)

          const tuple& other );
   template< class Alloc >
                                                               \fI(since C++11)\fP
   tuple( std::allocator_arg_t, const Alloc& a,           \fB(28)\fP (constexpr since C++20)

          tuple&& other );

   Constructs a new tuple.

   In the descriptions that follow, let

     * i be in the range [0, sizeof...(Types)) in order,
     * Ti be the ith type in Types, and
     * Ui be the ith type in a template parameter pack named UTypes,

   where indexing is zero-based.

   1) Default constructor. Value-initializes all elements, if any. The default
   constructor is trivial if sizeof...(Types) == 0.
     * This overload participates in overload resolution only if
       std::is_default_constructible<Ti>::value is true for all i.
     * The constructor is explicit if and only if Ti is not copy-list-initializable
       from {} for at least one i.
   2) Direct constructor. Initializes each element of the tuple with the corresponding
   parameter.
     * This overload participates in overload resolution only if sizeof...(Types) >= 1
       and std::is_copy_constructible<Ti>::value is true for all i.
     * This constructor is explicit if and only if std::is_convertible<const Ti&,
       Ti>::value is false for at least one i.
   3) Converting constructor. Initializes each element of the tuple with the
   corresponding value in std::forward<UTypes>(args).
     * This overload participates in overload resolution only if
          * sizeof...(Types) == sizeof...(UTypes),
          * sizeof...(Types) >= 1,
          * std::is_constructible<Ti, Ui>::value is true for all i, and
          * let D be
            std::decay<U0>::type
            \fI(until C++20)\fP
            std::remove_cvref_t<U0>
            \fI(since C++20)\fP,
               * if sizeof...(Types) == 1, then D is not std::tuple, otherwise,
               * if sizeof...(Types) == 2 or sizeof...(Types) == 3, then either D is
                 not std::allocator_arg_t, or T0 is std::allocator_arg_t.
     * The constructor is explicit if and only if std::is_convertible<Ui, Ti>::value is
       false for at least one i.

     * This constructor is defined as deleted if the initialization of
       any element that is a reference would bind it to a temporary       (since C++23)
       object.

   4-7) Converting constructor. Initializes each element of the tuple with the
   corresponding element of other.

   Formally, let FWD(other) be std::forward<decltype(other)>(other), for all i,
   initializes ith element of the tuple with std::get<i>(FWD(other)).

     * This overload participates in overload resolution only if
          * sizeof...(Types) == sizeof...(UTypes),
          * std::is_constructible_v<Ti, decltype(std::get<i>(FWD(other)))> is true for
            all i, and
          * either
               * sizeof...(Types) is not 1, or
               * (when Types... expands to T and UTypes... expands to U)
                 std::is_convertible_v<decltype(other), T>, std::is_constructible_v<T,
                 decltype(other)>, and std::is_same_v<T, U> are all false.
     * These constructors are explicit if and only if
       std::is_convertible_v<decltype(std::get<i>(FWD(other))), Ti> is false for at
       least one i.

     * These constructors are defined as deleted if the initialization of
       any element that is a reference would bind it to a temporary       (since C++23)
       object.

   8-11) Pair constructor. Constructs a 2-element tuple with each element constructed
   from the corresponding element of p.

   Formally, let FWD(p) be std::forward<decltype(p)>(p), initializes the first element
   with std::get<0>(FWD(p)) and the second element with std::get<1>(FWD(p)).

     * This overload participates in overload resolution only if
          * sizeof...(Types) == 2,
          * std::is_constructible_v<T0, decltype(std::get<0>(FWD(p)))> is true, and
          * std::is_constructible_v<T1, decltype(std::get<1>(FWD(p)))> is true.
     * The constructor is explicit if and only if
       std::is_convertible_v<decltype(std::get<0>(FWD(p))), T0> or
       std::is_convertible_v<decltype(std::get<1>(FWD(p))), T1> is false.

     * These constructors are defined as deleted if the initialization of
       any element that is a reference would bind it to a temporary       (since C++23)
       object.

   12) tuple-like constructor. Constructs a tuple with each element constructed from
   the corresponding element of u.

   Formally, for all i, initializes ith element of the tuple with
   std::get<i>(std::forward<UTuple>(u)).

     * This overload participates in overload resolution only if
          * std::same_as<std::remove_cvref_t<UTuple>, std::tuple> is false,
          * std::remove_cvref_t<UTuple> is not a specialization of
            std::ranges::subrange,
          * sizeof...(Types) equals std::tuple_size_v<std::remove_cvref_t<UTuple>>,
          * std::is_constructible_v<Ti, decltype(std::get<i>(std::forward<UTuple>(u)))>
            is true for all i, and
          * either
               * sizeof...(Types) is not 1, or
               * (when Types... expands to T) std::is_convertible_v<UTuple, T> and
                 std::is_constructible_v<T, UTuple> are both false.
     * This constructor is defined as deleted if the initialization of any element that
       is a reference would bind it to a temporary object.
   13) Implicitly-defined copy constructor. Initializes each element of the tuple with
   the corresponding element of other.
     * This constructor is constexpr if every operation it performs is constexpr. For
       the empty tuple std::tuple<>, it is constexpr.
     * std::is_copy_constructible<Ti>::value must be true for all i, otherwise
       the behavior is undefined
       \fI(until C++20)\fP
       the program is ill-formed
       \fI(since C++20)\fP.
   14) Implicitly-defined move constructor. For all i, initializes the ith element of
   the tuple with std::forward<Ui>(std::get<i>(other)).
     * This constructor is constexpr if every operation it performs is constexpr. For
       the empty tuple std::tuple<>, it is constexpr.
     * std::is_move_constructible<Ti>::value must be true for all i, otherwise
       the behavior is undefined
       \fI(until C++20)\fP
       this overload does not participate in overload resolution
       \fI(since C++20)\fP.
   15-28) Identical to (1-14) except each element is created by uses-allocator
   construction, that is, the Allocator object a is passed as an additional argument to
   the constructor of each element for which std::uses_allocator<Ui, Alloc>::value is
   true.

.SH Parameters

   args  - values used to initialize each element of the tuple
   other - the tuple of values used to initialize each element of the tuple
   p     - the pair of values used to initialize both elements of the 2-tuple
   u     - the tuple-like object of values used to initialize each element of the tuple
   a     - the allocator to use in uses-allocator construction

.SH Notes

   Conditionally-explicit constructors make it possible to construct a tuple in
   copy-initialization context using list-initialization syntax:

 std::tuple<int, int> foo_tuple()
 {
     // return {1, -1};             // Error before N4387
     return std::make_tuple(1, -1); // Always works
 }

   Note that if some element of the list is not implicitly convertible to the
   corresponding element of the target tuple, the constructors become explicit:

 using namespace std::chrono;
 void launch_rocket_at(std::tuple<hours, minutes, seconds>);

 launch_rocket_at({hours\fB(1)\fP, minutes\fB(2)\fP, seconds\fB(3)\fP}); // OK
 launch_rocket_at({1, 2, 3}); // Error: int is not implicitly convertible to duration
 launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // OK

.SH Example


// Run this code

 #include <iomanip>
 #include <iostream>
 #include <memory>
 #include <string>
 #include <string_view>
 #include <tuple>
 #include <type_traits>
 #include <vector>

 // helper function to print a vector to a stream
 template<class Os, class T>
 Os& operator<<(Os& os, std::vector<T> const& v)
 {
     os << '{';
     for (auto i{v.size()}; const T& e : v)
         os << e << (--i ? "," : "");
     return os << '}';
 }

 template<class T>
 void print_single(T const& v)
 {
     if constexpr (std::is_same_v<T, std::decay_t<std::string>>)
         std::cout << std::quoted(v);
     else if constexpr (std::is_same_v<std::decay_t<T>, char>)
         std::cout << "'" << v << "'";
     else
         std::cout << v;
 }

 // helper function to print a tuple of any size
 template<class Tuple, std::size_t N>
 struct TuplePrinter
 {
     static void print(const Tuple& t)
     {
         TuplePrinter<Tuple, N - 1>::print(t);
         std::cout << ", ";
         print_single(std::get<N - 1>(t));
     }
 };

 template<class Tuple>
 struct TuplePrinter<Tuple, 1>
 {
     static void print(const Tuple& t)
     {
         print_single(std::get<0>(t));
     }
 };

 template<class... Args>
 void print(std::string_view message, const std::tuple<Args...>& t)
 {
     std::cout << message << " (";
     TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
     std::cout << ")\\n";
 }
 // end helper function

 int main()
 {
     std::tuple<int, std::string, double> t1;
     print("Value-initialized, t1:", t1);

     std::tuple<int, std::string, double> t2{42, "Test", -3.14};
     print("Initialized with values, t2:", t2);

     std::tuple<char, std::string, int> t3{t2};
     print("Implicitly converted, t3:", t3);

     std::tuple<int, double> t4{std::make_pair(42, 3.14)};
     print("Constructed from a pair, t4:", t4);

     // given Allocator my_alloc with a single-argument constructor
     // my_alloc(int); use my_alloc(1) to allocate 5 ints in a vector
     using my_alloc = std::allocator<int>;
     std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}};

     // use my_alloc(2) to allocate 5 ints in a vector in a tuple
     std::tuple<int, std::vector<int, my_alloc>, double> t5
         {std::allocator_arg, my_alloc{/* 2 */}, 42, v, -3.14};
     print("Constructed with allocator, t5:", t5);
 }

.SH Possible output:

 Value-initialized, t1: (0, "", 0)
 Initialized with values, t2: (42, "Test", -3.14)
 Implicitly converted, t3: ('*', "Test", -3)
 Constructed from a pair, t4: (42, 3.14)
 Constructed with allocator, t5: (42, {1,1,1,1,1}, -3.14)

   Defect reports

   The following behavior-changing defect reports were applied retroactively to
   previously published C++ standards.

      DR    Applied to        Behavior as published              Correct behavior
   LWG 2510 C++11      default constructor was implicit     made conditionally-explicit
                       constructor of 1-tuple might
   LWG 3121 C++11      recursively check the constraints;   furtherly constrained
                       allocator_arg_t argument brought     the constructor
                       ambiguity
                       the uses-allocator constructor
   LWG 3158 C++11      corresponding                        made conditionally-explicit
                       to default constructor was implicit
   LWG 3211 C++11      whether the default constructor of   require to be trivial
                       tuple<> is trivial was unspecified
   N4387    C++11      some constructors were explicit,     most constructors made
                       preventing useful behavior           conditionally-explicit
                       tuple-like constructor may
   LWG 4045 C++23      potentially create dangling          made defined as deleted
                       references

.SH See also

   operator=        assigns the contents of one tuple to another
                    \fI(public member function)\fP
   make_tuple       creates a tuple object of the type defined by the argument types
   \fI(C++11)\fP          \fI(function template)\fP
   tie              creates a tuple of lvalue references or unpacks a tuple into
   \fI(C++11)\fP          individual objects
                    \fI(function template)\fP
   forward_as_tuple creates a tuple of forwarding references
   \fI(C++11)\fP          \fI(function template)\fP
   constructor      constructs new pair
                    \fI(public member function of std::pair<T1,T2>)\fP
